// Vector.h
 
// Matematicky vektor

#ifndef VECTOR_H
#define VECTOR_H

#include "Common/World/Angle.h"

// Deklaracia bodu
class Point;

// Vektor v ortogonal. suranicovej sustave
class Vector
{
	// Rozmery x, y vektora
	float xSize, ySize;
	// Dlzka vektora (mala by byt nezaporna, ale v tejto triede nie je)
	float length;
	// Uhol zvierajuci s x-ovou osou
	Angle angle;

protected:
	// Nastavi a vypocita dlzku vektora a uhol, ktory zviera s X-ovou osou 
	void AdjustAng();
	// Nastavi a vypocita x-ovu a y-ovu velkost vektora
	void AdjustXY();

public:
	// Konstruktor bez parametrov
	Vector() : length(0), xSize(0), ySize(0)
	{
	
	}
	// Kopirovaci konstruktor
	inline Vector(const Vector &vect);

	// Metody pristupu
	
	float GetX() const
	{ 
		return xSize;
	}
	float GetY() const
	{ 
		return ySize; 
	}

	float GetLength() const
	{ 
		return length;
	}
	Angle GetAngle() const
	{ 
		return angle;
	}

	// Metody zapisu
	void SetX(float x)
	{ 
		xSize = x; AdjustAng(); 
	}
	void SetY(float y)
	{ 
		ySize = y; AdjustAng(); 
	}
	
	void SetLength(float len)
	{ 
		length = len; 
		AdjustXY();
	}
	void SetAngle(Angle ang)
	{ 
		angle = ang;
		AdjustXY();
	}

	// Operatory
	inline Vector	operator +(const Vector& vect)	const;
	inline Point	operator +(const Point& pos)	const;
	inline Vector	operator -(const Vector& vect)	const;

	inline const Vector& operator =(const Vector& vect);
	inline const Vector& operator +=(const Vector& vect);
	inline const Vector& operator -=(const Vector& vect);

	inline Vector operator *(float f) const;
	inline Vector operator /(float f) const;
	inline Vector operator +(Angle a) const;
	inline Vector operator -(Angle a) const;

	const Vector& operator *=(float f)
	{ 
		length *= f; AdjustXY(); 
		return *this;
	}
	const Vector& operator /=(float f)
	{ 
		length /= f; AdjustXY();
		return *this; 
	}
	const Vector& operator +=(Angle a)
	{ 
		angle += a; AdjustXY();
		return *this; 
	}
	const Vector& operator -=(Angle a)
	{ 
		angle -= a; AdjustXY(); 
		return *this;
	}

	// Otocenie vektora o 90 stupnov proti smeru hodinovych ruciciek
	inline Vector OrthoLeft() const;
	// Otocenie vektora o 90 stupnov v smere hodinovych ruciciek
	inline Vector OrthoRight() const;

//	static float RadToDeg(float angle) { return angle * 180.f / M_PI; }
//	static float DegToRad(float angle) { return angle * M_PI / 180.f; }
//	static inline float NormDeg(float angle);
//	static inline float NormRad(float angle);
};

// Klasicky obdlznikovy vektor
class RectVector : public Vector
{
public:
	// Konstruktor
	RectVector(float x, float y)
	{ 
		SetX(x); SetY(y); 
		AdjustAng();
	}
};
// Polarny vektor s dlzkou l
class PolarVector : public Vector
{
public:
	// Konstruktor (nepliest si parameter l s 1!)
	PolarVector(float l, Angle a)
	{ 
		SetLength(l);
		SetAngle(a); 
		AdjustXY();
	}
};


// Tento "include" musi byt presne tu, inak sa to nepaci suboru "point.h"
#include "Common/World/Point.h"

Vector::Vector(const Vector &vect)
{
	length = vect.length;
	angle = vect.angle;
	xSize = vect.xSize;
	ySize = vect.ySize;
}


Vector Vector::operator +(const Vector& vect) const
{
	return RectVector(xSize + vect.xSize, ySize + vect.ySize);
}

Point Vector::operator +(const Point& point) const
{
	return Point(xSize + point.GetX(), ySize + point.GetY());
}

Vector Vector::operator -(const Vector& vect) const
{
	return RectVector(xSize - vect.xSize, ySize - vect.ySize);
}


const Vector& Vector::operator =(const Vector& vect)
{
	xSize = vect.xSize; ySize = vect.ySize;
	length = vect.length; 
	angle = vect.angle;
	return *this;
}

const Vector& Vector::operator +=(const Vector& vect)
{
	xSize += vect.xSize; ySize += vect.ySize;
	AdjustAng();
	return *this;
}

const Vector& Vector::operator -=(const Vector& vect)
{
	xSize -= vect.xSize; ySize -= vect.ySize;
	AdjustAng();
	return *this;
}


Vector Vector::operator *(float f) const
{
	return PolarVector(length * f, angle);
}

Vector Vector::operator /(float f) const
{
	// Pozor, ak f = 0, ide od delenie 0 !!!
	return PolarVector(length / f, angle);
}

Vector Vector::operator +(Angle a) const
{
	return PolarVector(length, angle + a);
}

Vector Vector::operator -(Angle a) const
{
	return PolarVector(length, angle - a);
}

// Otocenie vektora o 90 stupnov proti smeru hodinovych ruciciek
Vector Vector::OrthoLeft() const
{
	return RectVector(-ySize, xSize);
}

// Otocenie vektora o 90 stupnov v smere hodinovych ruciciek
Vector Vector::OrthoRight() const
{
	return RectVector(ySize, -xSize);
}

/*float Vector::NormDeg(float angle)
{
	while(angle < 180.f) angle += 360.f;
	while(angle > 180.f) angle -= 360.f;
	return angle;
}*/

/*float Vector::NormRad(float angle)
{
	while(angle < M_PI) angle += 2 * M_PI;
	while(angle > M_PI) angle -= 2 * M_PI;
	return angle;
}*/

#endif // VECTOR_H
